/*
 * 文件名： MerSettledPabBankServiceImpl.java
 * 
 * 工程名称: bis-bank-pab
 *
 * Gopay
 *
 * 创建日期： 2018年1月3日
 *
 * Copyright(C) 2018, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.pab.apay.impl;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.gopay.bis.pab.apay.operation.PabApayHelper;
import com.gopay.bis.pab.apay.operation.Transport;
import com.gopay.common.constants.bank.PabConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.merchant.MerchantSettledMessage;
import com.gopay.common.domain.bank.merchant.MerchantSettledOrgResMsg;
import com.gopay.common.domain.bank.merchant.MerchantSettledResMessage;
import com.gopay.common.domain.bank.merchant.contract.res.ContractAddResMsg;
import com.gopay.common.domain.bank.merchant.contract.res.ContractDeleteResMsg;
import com.gopay.common.domain.bank.merchant.contract.res.ContractEditResMsg;
import com.gopay.common.domain.bank.merchant.contract.res.ContractPayFeeResMsg;
import com.gopay.common.domain.bank.merchant.contract.res.ContractPayListResMsg;
import com.gopay.common.domain.bank.merchant.contract.res.ContractRelateResMsg;
import com.gopay.common.domain.bank.merchant.mer.res.MerchantAddResMsg;
import com.gopay.common.domain.bank.merchant.mer.res.MerchantCityResMsg;
import com.gopay.common.domain.bank.merchant.mer.res.MerchantClassResMsg;
import com.gopay.common.domain.bank.merchant.mer.res.MerchantDeleteResMsg;
import com.gopay.common.domain.bank.merchant.mer.res.MerchantEditResMsg;
import com.gopay.common.domain.bank.merchant.shop.res.ShopAddResMsg;
import com.gopay.common.domain.bank.merchant.shop.res.ShopDeleteResMsg;
import com.gopay.common.domain.bank.merchant.shop.res.ShopEditResMsg;
import com.gopay.common.domain.bank.merchant.shop.res.ShopOpenIdResMsg;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.FastJsonUtil;
import com.gopay.remote.bank.businesses.MerchantSettledService;

/**
 * 商户入驻-平安银行数据交互业务处理
 *
 * @author 宣广海
 *
 * @version
 *
 * @since 2018年1月3日
 */
@SuppressWarnings("rawtypes")
public class MerSettledPabBankServiceImpl implements MerchantSettledService {
	/**
	 * 日志对象
	 */
	private static Logger logger = LoggerFactory.getLogger(MerSettledPabBankServiceImpl.class);

	private PabApayHelper aPayPabHelper;
	/**
	 * 私钥证书
	 */
	private String privateKey;
	/**
	 * 公钥证书
	 */
	private String publicKey;

	@Override
	public Object handle(MerchantSettledMessage message) throws GopayException {
		MerchantSettledResMessage resMessage = new MerchantSettledResMessage();
		String returnStr = null;
		try {
			TreeMap<String, String> getmap = generateMerchantGetParam(message);
			Map<String, String> param = generateMerchantParam(message, getmap);
			// 发送报文到银行
			returnStr = Transport.handleMerchantPost((TreeMap<String, String>) param, getmap, message.getUrl(),
					message.getInterfaceName());
			logger.info(message.getInterfaceName() + "接口返回报文为：" + returnStr);
			if (!returnStr.isEmpty()) {
				JSONObject respObject = JSONObject.parseObject(returnStr);
				Object dataStr = respObject.get("data");
				resMessage.setErrcode(respObject.get("errcode").toString());
				resMessage.setMsg(respObject.get("msg").toString());
				if (null != dataStr) {
					// 验签
					if (aPayPabHelper.verifyMerchant(respObject, publicKey)) {
						/*
						 * AES解密，并hex2bin
						 */
						String respData = aPayPabHelper.decrypt(dataStr.toString(), message.getMerKey());
						logger.info(message.getInterfaceName() + "接口返回明文报文为：" + respData);
						resMessage = generateResMsg(resMessage, message, respData);
					} else {
						throw new GopayException(ProcCodeConstants.PROC_CODE_100E8004);
					}
				}
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100F1002);
		}
	}

	@Override
	public Object verify(MerchantSettledMessage message) throws GopayException {
		JSONObject respObject = JSONObject.parseObject(message.getPlainMessage());
		return aPayPabHelper.verifyMerchant(respObject, publicKey);
	}

	@SuppressWarnings("unchecked")
	private MerchantSettledResMessage generateResMsg(MerchantSettledResMessage resMessage,
			MerchantSettledMessage message, String respData) {
		if (PabConstants.MERCHANT_ADD.equals(message.getInterfaceName())) {
			MerchantAddResMsg returnMessage = handleReturnMessage(respData, MerchantAddResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.MERCHANT_EDIT.equals(message.getInterfaceName())) {
			MerchantEditResMsg returnMessage = handleReturnMessage(respData, MerchantEditResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.MERCHANT_DELETE.equals(message.getInterfaceName())) {
			MerchantDeleteResMsg returnMessage = handleReturnMessage(respData, MerchantDeleteResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.MERCHANT_CLASS.equals(message.getInterfaceName())) {
			//MerchantClassResMsg returnMessage = handleReturnMessage(respData, MerchantClassResMsg.class);
			List resList=FastJsonUtil.toList(respData, MerchantClassResMsg.class);
			resMessage.setBody(resList);
		} else if (PabConstants.MERCHANT_CITY.equals(message.getInterfaceName())) {
			//MerchantCityResMsg returnMessage = handleReturnMessage(respData, MerchantCityResMsg.class);
			List resList=FastJsonUtil.toList(respData, MerchantCityResMsg.class);
			resMessage.setBody(resList);
		} else if (PabConstants.SHOP_ADD.equals(message.getInterfaceName())) {
			ShopAddResMsg returnMessage = handleReturnMessage(respData, ShopAddResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.SHOP_EDIT.equals(message.getInterfaceName())) {
			ShopEditResMsg returnMessage = handleReturnMessage(respData, ShopEditResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.SHOP_DELETE.equals(message.getInterfaceName())) {
			ShopDeleteResMsg returnMessage = handleReturnMessage(respData, ShopDeleteResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.SHOP_OPENID.equals(message.getInterfaceName())) {
			ShopOpenIdResMsg returnMessage = handleReturnMessage(respData, ShopOpenIdResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.CONTRACT_PAYLIST.equals(message.getInterfaceName())) {
//			ContractPayListResMsg returnMessage = handleReturnMessage(respData, ContractPayListResMsg.class);
//			resMessage.setBody(returnMessage);
			List resList=FastJsonUtil.toList(respData, ContractPayListResMsg.class);
			resMessage.setBody(resList);
		} else if (PabConstants.CONTRACT_PAYFEE.equals(message.getInterfaceName())) {
			ContractPayFeeResMsg returnMessage = handleReturnMessage(respData, ContractPayFeeResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.CONTRACT_ADD.equals(message.getInterfaceName())) {
			ContractAddResMsg returnMessage = handleReturnMessage(respData, ContractAddResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.CONTRACT_EDIT.equals(message.getInterfaceName())) {
			ContractEditResMsg returnMessage = handleReturnMessage(respData, ContractEditResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.CONTRACT_DELETE.equals(message.getInterfaceName())) {
			ContractDeleteResMsg returnMessage = handleReturnMessage(respData, ContractDeleteResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.CONTRACT_RELATE.equals(message.getInterfaceName())) {
			ContractRelateResMsg returnMessage = handleReturnMessage(respData, ContractRelateResMsg.class);
			resMessage.setBody(returnMessage);
		} else if (PabConstants.FILE_UPLODE.equals(message.getInterfaceName())) {
			MerchantSettledOrgResMsg returnMessage = handleReturnMessage(respData, MerchantSettledOrgResMsg.class);
			resMessage.setBody(returnMessage);
		}
		return resMessage;
	}

	private <T> T handleReturnMessage(String json, Class<T> clazz) {
		T t = FastJsonUtil.toBean(json, clazz);
		return t;
	}

	/**
	 * 
	 * 功能描述：构建上送进件业务银行参数
	 *
	 * @param message
	 * @param getmap
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2018年1月6日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Map<String, String> generateMerchantParam(MerchantSettledMessage message, TreeMap<String, String> getmap)
			throws GopayException {
		TreeMap<String, String> postmap = new TreeMap<String, String>();
		try {
			/*
			 * 1 data（JSON）字段内容进行AES加密，再二进制转十六进制(bin2hex)
			 */
			if (StringUtils.isNotBlank(message.getPlainMessage())) {
				String data = aPayPabHelper.encrypt(message.getPlainMessage(), message.getMerKey());
				postmap.put("data", data);
			}
			/*
			 * 2 请求参数签名 按A~z排序，串联成字符串，先进行sha1加密(小写)，再进行md5加密(小写)，得到签名
			 */
			String signData = aPayPabHelper.handleMerchantSign(getmap, postmap, privateKey);
			postmap.put("sign", signData);
			if(!PabConstants.FILE_UPLODE.equals(message.getInterfaceName())){
				logger.info("merchant submit param :" + postmap);
			}	
		} catch (Exception e) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_000F1002);
		}
		return postmap;
	}

	/**
	 * 
	 * 功能描述：构建请求接口get方式参数
	 *
	 * @param message
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2018年1月6日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public TreeMap<String, String> generateMerchantGetParam(MerchantSettledMessage message) throws GopayException {
		TreeMap<String, String> getmap = new TreeMap<String, String>();
		try {
			getmap.put("open_id", message.getMerId());
			getmap.put("lang", message.getLang());
			getmap.put("timestamp", message.getTimestamp());
			getmap.put("randStr", message.getRandStr());
		} catch (Exception e) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_000F1002);
		}
		return getmap;
	}

	public PabApayHelper getaPayPabHelper() {
		return aPayPabHelper;
	}

	public void setaPayPabHelper(PabApayHelper aPayPabHelper) {
		this.aPayPabHelper = aPayPabHelper;
	}

	public String getPrivateKey() {
		return privateKey;
	}

	public void setPrivateKey(String privateKey) {
		this.privateKey = privateKey;
	}

	public String getPublicKey() {
		return publicKey;
	}

	public void setPublicKey(String publicKey) {
		this.publicKey = publicKey;
	}

}
